﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Windows;
using System.Data;
using RAE.Logica.Info;
using RAE.Logica.Controladores;
using RAE.Logica.Torneos;

namespace RAE.Persistencia
{
    public static class Cargador
    {
        private static SqlConnection conexion;

        public static void inicializar()
        {
            SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder();
            scsb.DataSource = ".\\SQLEXPRESS";
            scsb.UserID = "ChessProject";
            scsb.Password = "Password123$";
            scsb.InitialCatalog = "Ajedrez";

            conexion = new SqlConnection(scsb.ConnectionString);
            try
            {
                conexion.Open();
            }
            catch (SqlException x)
            {
                MessageBox.Show("No fue posible conectarse con la base de datos. Contacte a los desarrolladores de la aplicación para asistencia técnica.");
                System.Windows.Forms.Application.Exit();
            }
        }

        public static void desconectar()
        {
            try
            {
                conexion.Close();
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
        }

        public static List<Ajedrecista> obtenerAjerecistas()
        {
            List<Ajedrecista> ajedrecistas = new List<Ajedrecista>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarAjedrecistas", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    Ajedrecista ajedrecista = new Ajedrecista();

                    ajedrecista.id = (int   ) rdr["ID"       ];

                    ajedrecista.nombre      = (String) rdr["Nombre"          ];
                    ajedrecista.apellidos   = (String) rdr["Apellidos"       ];
                    ajedrecista.cedula      = (String) rdr["Cedula"          ];
                    ajedrecista.puntaje_elo = (int   ) rdr["PuntajeEloActual"];
                    
                    // Categoria se determina con el puntaje Elo y los datos de las categorías
                    // Títulos se cargan aparte

                    ajedrecista.fechaRegistro = rdr["FechaRegistro"].Equals(DBNull.Value) ? new DateTime() : (DateTime)rdr["FechaRegistro"];
                    ajedrecista.fechaNacimiento = rdr["FechaNacimiento"].Equals(DBNull.Value) ? new DateTime?() : (DateTime?)rdr["FechaNacimiento"];
                  
                    ajedrecista.fechaDeceso = rdr["FechaDeceso"].Equals(DBNull.Value) ? new DateTime?() : (DateTime?)rdr["FechaDeceso"];


                    ajedrecista.esResidente = ((bool)rdr["EsResidente"]);
                    ajedrecista.nacionalidad = Aplicacion.paises[(short) rdr["FK_Pais"]];
        
                    ajedrecista.tel_residencia = (String) rdr["TelResidencia"];
                    ajedrecista.tel_celular    = (String) rdr["TelCelular"   ];
                    ajedrecista.email          = (String) rdr["Email"        ];
                    ajedrecista.comentario     = (String) rdr["Comentario"   ];
                    ajedrecista.fotografia = rdr["Fotografia"].Equals(DBNull.Value) ? new byte[0] : (byte[])rdr["Fotografia"];

                    ajedrecista.estadisticas.pBlancas = rdr["PBlancas"].Equals(DBNull.Value) ? 0 : (int) rdr["PBlancas"];
                    ajedrecista.estadisticas.pNegras  = rdr["PNegras" ].Equals(DBNull.Value) ? 0 : (int) rdr["PNegras" ];
                    ajedrecista.estadisticas.gBlancas = rdr["GBlancas"].Equals(DBNull.Value) ? 0 : (int) rdr["GBlancas"];
                    ajedrecista.estadisticas.gNegras =  rdr["GNegras" ].Equals(DBNull.Value) ? 0 : (int) rdr["GNegras" ];

                    ajedrecistas.Add(ajedrecista);

                }
                rdr.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return ajedrecistas;
        }

        public static List<Categoria> obtenerCategorias()
        {
            List<Categoria> categorias = new List<Categoria>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarCategorias", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    int    id              = (int   ) rdr["ID"];
                    String nombre          = (String) rdr["Nombre"];
                    int    puntaje_elo_min = (int   ) rdr["PuntajeEloMinimo"];
                    int    coeficiente     = (int)    rdr["Coeficiente"];

                    categorias.Add(new Categoria(id, nombre, puntaje_elo_min, coeficiente));
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }

            return categorias;
        }
       
        public static List<Periodo> obtenerPeriodos()
        {
            List<Periodo> periodos = new List<Periodo>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarPeriodos", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    int id = (int)rdr["ID"];
                    DateTime fecha = (DateTime)rdr["Fecha"];

                    periodos.Add(new Periodo(id, fecha));
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }

            return periodos;
        }

        public static void obtenerHistorialElo(Ajedrecista a)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarHistorialElo", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@IdAjedrecista", a.id));
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    ((Historia)a.historial.Select(h => h).Where(h => h.periodo.id == (int)rdr["ID"]).First()).puntajeElo = (int)rdr["Puntaje"];
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }
        }

        public static Dictionary<int,Titulo> obtenerTitulos()
        {
            Dictionary<int,Titulo> titulos = new Dictionary<int,Titulo>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarTitulos", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    int    id     = (int   ) rdr["ID"    ];
                    String nombre = (String) rdr["Nombre"];
                    String codigo = (String) rdr["Codigo"];

                    titulos.Add(id, new Titulo(id, nombre, codigo));
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }

            return titulos;
        }

        public static Dictionary<int,Pais> obtenerPaises()
        {
            Dictionary<int,Pais> paises = new Dictionary<int,Pais>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarPaises", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    int    id     = (short)    rdr["ID"];
                    String nombre = (String) rdr["Nombre"];

                    paises.Add(id, new Pais(id, nombre));
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }

            return paises;
        }

        public static Dictionary<int, Torneo> obtenerTorneos()
        {
            Dictionary<int, Torneo> torneos = new Dictionary<int, Torneo>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarPaises", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                while (rdr.Read())
                {
                    Torneo t = new Torneo();

                    t.id = (int) rdr["ID"];
                    t.nombre = (String)rdr["Nombre"];
                    t.fecha_fin = (DateTime)rdr["FechaFin"];
                    t.fecha_inicio = (DateTime)rdr["FechaInicio"];
                    t.lugar = (String)rdr["Lugar"];
                    t.comentario = (String)rdr["Comentario"];
                    t.cantidad_rondas = (int) rdr["CantidadRondas"];

                    torneos.Add(t.id, t);
                }

                rdr.Close();
            }
            catch (Exception e)
            {

            }

            return torneos;
        }

        public static int obtenerPuntajeEloMin()
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarConfiguracion", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlDataReader rdr = command.ExecuteReader();
                rdr.Read();
                
                int result = (int) rdr["PuntajeEloMin"];
                rdr.Close();
                return result;
            }
            catch (Exception e)
            {
                return 0;
            }
        }

        public static List<Titulo> obtenerTitulosPorAjedrecista(Ajedrecista ajedrecista)
        {   
            List<Titulo> titulos = new List<Titulo>();
            try
            {
                SqlCommand command = new SqlCommand("SP_ConsultarTitulosAjedrecista", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@idAjedrecista", ajedrecista.id));
                SqlDataReader rdr = command.ExecuteReader();

                while (rdr.Read())
                    titulos.Add(Aplicacion.titulos[(int) rdr["FKID_Titulo"]]);

                rdr.Close();
            }
            catch (Exception e)
            {

            }
            return titulos;
        }

        public static bool autenticarEncargadoElo(string pass)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_AutenticarEncargado", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@pass", pass));
                SqlDataReader rdr = command.ExecuteReader();

                bool autenticado = rdr.HasRows;
                rdr.Close();
                return autenticado;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        public static bool autenticarAdministrador(string pass)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_AutenticarAdmin", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@pass", pass));
                SqlDataReader rdr = command.ExecuteReader();

                bool autenticado = rdr.HasRows;
                rdr.Close();
                return autenticado;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        public static void registrarAjedrecista(Ajedrecista a)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_RegistrarAjedrecista", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@nombre", a.nombre));
                command.Parameters.Add(new SqlParameter("@apellidos", a.apellidos));
                command.Parameters.Add(new SqlParameter("@cedula", a.cedula));
                command.Parameters.Add(new SqlParameter("@puntajeElo", a.puntaje_elo));
                command.Parameters.Add(new SqlParameter("@fechaNacimiento", a.fechaNacimiento));
                command.Parameters.Add(new SqlParameter("@idPais", a.nacionalidad.id));
                command.Parameters.Add(new SqlParameter("@esResidente", a.esResidente));
                command.Parameters.Add(new SqlParameter("@telResidencia", a.tel_residencia));
                command.Parameters.Add(new SqlParameter("@telCelular", a.tel_celular));
                command.Parameters.Add(new SqlParameter("@email", a.email));
                command.Parameters.Add(new SqlParameter("@comentario", a.comentario));
                command.Parameters.Add(new SqlParameter("@foto", a.fotografia));
                SqlDataReader rdr = command.ExecuteReader();

                rdr.Close();
            }
            catch (Exception e)
            {
                
            }
        }

        public static void actualizarAjedrecista(Ajedrecista a)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ModificarAjedrecista", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@idAjedrecista", a.id));
                command.Parameters.Add(new SqlParameter("@nombre", a.nombre));
                command.Parameters.Add(new SqlParameter("@apellidos", a.apellidos));
                command.Parameters.Add(new SqlParameter("@cedula", a.cedula));
                command.Parameters.Add(new SqlParameter("@puntajeElo", a.puntaje_elo));
                command.Parameters.Add(new SqlParameter("@fechaNacimiento", a.fechaNacimiento));
                command.Parameters.Add(new SqlParameter("@fechaDeceso", a.fechaDeceso));
                command.Parameters.Add(new SqlParameter("@idPais", a.nacionalidad.id));
                command.Parameters.Add(new SqlParameter("@esResidente", a.esResidente));
                command.Parameters.Add(new SqlParameter("@telResidencia", a.tel_residencia));
                command.Parameters.Add(new SqlParameter("@telCelular", a.tel_celular));
                command.Parameters.Add(new SqlParameter("@email", a.email));
                command.Parameters.Add(new SqlParameter("@comentario", a.comentario));
                command.Parameters.Add(new SqlParameter("@foto", a.fotografia));
                SqlDataReader rdr = command.ExecuteReader();

                rdr.Close();
            }
            catch (Exception e)
            {

            }
        }
        public static void modificarEloMinimo(int elo)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ModificarPuntajeEloMin", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@elo", elo));

                SqlDataReader rdr = command.ExecuteReader();
                rdr.Close();
            }
            catch (Exception e)
            { 
            
            }
        }
        public static Periodo agragarPeriodo()
        {
            Periodo periodo = new Periodo();
            try
            {
                SqlCommand command = new SqlCommand("SP_CrearCorte", conexion);
                command.CommandType = CommandType.StoredProcedure;
                SqlParameter returnValueParam = command.Parameters.Add("@return_value", SqlDbType.Int);
                returnValueParam.Direction = ParameterDirection.ReturnValue;
                command.ExecuteNonQuery();
                periodo = new Periodo((int)returnValueParam.Value, DateTime.Now);
                Aplicacion.periodos.Add(periodo);
            }
            catch (Exception e)
            { }
            return periodo;
        }
        public static void actualizarHistorial(Ajedrecista a)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ActualizarHistorialElo", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@Ajedrecista", a.id));
                SqlDataReader rdr = command.ExecuteReader();
                rdr.Close();                
            }
            catch (Exception e)
            {

            }
       }
        public static void actualizarElo(Ajedrecista a)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ActualizarElo", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@Ajedrecista", a.id));
                command.Parameters.Add(new SqlParameter("@Elo", a.puntaje_elo));
                SqlDataReader rdr = command.ExecuteReader();
                rdr.Close();
            }
            catch (Exception e)
            {

            }
        }

        public static void agregarCategoria(Categoria categoria)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_AgregarCategoria", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@nombre", categoria.nombre));
                command.Parameters.Add(new SqlParameter("@elo", categoria.puntaje_elo_min));
                command.Parameters.Add(new SqlParameter("@coeficiente", categoria.coeficiente));
                SqlDataReader rdr = command.ExecuteReader();

                rdr.Close();
            }
            catch (Exception e) { }
        }
        
        public static void modificarCategoria(Categoria categoria)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_ModificarCategoria", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@nombre", categoria.nombre));
                command.Parameters.Add(new SqlParameter("@elo", categoria.puntaje_elo_min));
                command.Parameters.Add(new SqlParameter("@coeficiente", categoria.coeficiente));
                SqlDataReader rdr = command.ExecuteReader();

                rdr.Close();
            }
            catch (Exception e) { }
        }

        public static void borrarCategoria(Categoria categoria)
        {
            try
            {
                SqlCommand command = new SqlCommand("SP_BorrarCategoria", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@nombre", categoria.nombre));
                SqlDataReader rdr = command.ExecuteReader();

                rdr.Close();
            }
            catch (Exception e) { }
        }

        public static void registrarTorneo(Torneo t)
        {
            try
            {
                registrarTorneoSencillo(t);

                foreach (FilaCrosstable f in t.crosstable)
                    registrarFilaCrosstable(f, t.id);
            }
            catch (Exception e)
            {

            }
        }

        private static void registrarTorneoSencillo(Torneo t)
        {
            SqlCommand command = new SqlCommand("SP_RegistrarTorneo", conexion);
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter("@nombre", t.nombre));
            command.Parameters.Add(new SqlParameter("@fecha_inicio", t.fecha_inicio));
            command.Parameters.Add(new SqlParameter("@fecha_fin", t.fecha_fin));
            command.Parameters.Add(new SqlParameter("@lugar", t.lugar));
            command.Parameters.Add(new SqlParameter("@comentario", t.comentario));
            command.Parameters.Add(new SqlParameter("@rondas", t.cantidad_rondas));

            SqlDataReader rdr = command.ExecuteReader();
            if (rdr.Read())
                t.id = rdr.GetInt32(0);

            rdr.Close();
        }
        
        private static void registrarFilaCrosstable(FilaCrosstable f, int id_torneo)
        {
            SqlCommand command = new SqlCommand("SP_RegistrarAjedrecistaPorTorneo", conexion);
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter("@id_ajedrecista", f.ajedrecista.id));
            command.Parameters.Add(new SqlParameter("@id_torneo", id_torneo));
            command.Parameters.Add(new SqlParameter("@indice", f.idx));

            int id_axt = 0;
            SqlDataReader rdr = command.ExecuteReader();
            if (rdr.Read())
                id_axt = rdr.GetInt32(0);
            
            rdr.Close();

            for (int i=0; i < f.resultados.Count; i++)
            {
                command = new SqlCommand("SP_RegistrarResultadoRonda", conexion);
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new SqlParameter("@id_axt", id_axt));
                command.Parameters.Add(new SqlParameter("@ronda", i));
                command.Parameters.Add(new SqlParameter("@resultado", f.resultados[i]));

                rdr = command.ExecuteReader();
                rdr.Close();
            }
        }
    }
}
